/*---------------------------------------------------------------------
 * File name: hal_spi.h
 *
 * Copyright (c) <2020-2022>, <ChenLong>
 *
 * All rights reserved.
 *
 * Author: ChenLong
 * Email: worldlong@foxmail.com
 *--------------------------------------------------------------------*/
#pragma once
/*
*/
#include "hal_gpio.h"
/*
*/
#define HSPI_PORT_BITS    3
#define HSPI_MODE_BITS    1
#define HSPI_DATA_BITS    1
#define HSPI_WIRE_BITS    1
#define HSPI_CPOL_BITS    1
#define HSPI_CPHA_BITS    1
#define HSPI_NSS_BITS     1
#define HSPI_FB_BITS      1
#define HSPI_BRP_BITS     10
/*
*/
#define HSPI_PORT_POS    (0)
#define HSPI_MODE_POS    (HSPI_PORT_POS + HSPI_PORT_BITS)
#define HSPI_DATA_POS    (HSPI_MODE_POS + HSPI_MODE_BITS)
#define HSPI_WIRE_POS    (HSPI_DATA_POS + HSPI_DATA_BITS)
#define HSPI_CPOL_POS    (HSPI_WIRE_POS + HSPI_WIRE_BITS)
#define HSPI_CPHA_POS    (HSPI_CPOL_POS + HSPI_CPOL_BITS)
#define HSPI_NSS_POS     (HSPI_CPHA_POS + HSPI_CPHA_BITS)
#define HSPI_FB_POS      (HSPI_NSS_POS + HSPI_NSS_BITS)
#define HSPI_BRP_POS     (HSPI_FB_POS + HSPI_FB_BITS)
/*
*/
#define HSPI_PORT_MASK   ((1<<HSPI_PORT_BITS) - 1)
#define HSPI_MODE_MASK   ((1<<HSPI_MODE_BITS) - 1)
#define HSPI_DATA_MASK   ((1<<HSPI_DATA_BITS) - 1)
#define HSPI_WIRE_MASK   ((1<<HSPI_WIRE_BITS) - 1)
#define HSPI_CPOL_MASK   ((1<<HSPI_CPOL_BITS) - 1)
#define HSPI_CPHA_MASK   ((1<<HSPI_CPHA_BITS) - 1)
#define HSPI_NSS_MASK    ((1<<HSPI_NSS_BITS) - 1)
#define HSPI_FB_MASK     ((1<<HSPI_FB_BITS) - 1)
#define HSPI_BRP_MASK    ((1<<HSPI_BRP_BITS) - 1)
#define HSPI_CFG_MASK    ((HSPI_MODE_MASK << HSPI_MODE_POS) |\
                          (HSPI_WIRE_MASK << HSPI_WIRE_POS) |\
                          (HSPI_CPOL_MASK << HSPI_CPOL_POS) |\
                          (HSPI_CPHA_MASK << HSPI_CPHA_POS) |\
                          (HSPI_NSS_MASK << HSPI_NSS_POS) |\
                          (HSPI_FB_MASK <<HSPI_FB_POS) |\
                          (HSPI_BRP_MASK <<HSPI_BRP_POS))
/*
*/
#define HSPI_0 (1 << HSPI_PORT_POS)
#define HSPI_1 (2 << HSPI_PORT_POS)
#define HSPI_2 (3 << HSPI_PORT_POS)
#define HSPI_3 (4 << HSPI_PORT_POS)
#define HSPI_4 (5 << HSPI_PORT_POS)
#define HSPI_5 (6 << HSPI_PORT_POS)
#define HSPI_6 (7 << HSPI_PORT_POS)
#define HSPI_7 (8 << HSPI_PORT_POS)
#define HSPI_PORT(param)  (HSPI_##param >> HSPI_PORT_POS)
/*
*/
#define HSPI_MODE_MASTER  (0 << HSPI_MODE_POS)
#define HSPI_MODE_SLAVE   (1 << HSPI_MODE_POS)
#define HSPI_MODE(param)  (HSPI_MODE_##param >> HSPI_MODE_POS)
/*
*/
#define HSPI_DATA_8B      (0 << HSPI_DATA_POS)
#define HSPI_DATA_16B     (1 << HSPI_DATA_POS)
#define HSPI_DATA(param)  (HSPI_DATA_##param >> HSPI_DATA_POS)
/*
*/
#define HSPI_WIRE_2L1D    (0 << HSPI_WIRE_POS)   //MOSI and MISO connected
#define HSPI_WIRE_2L2D    (1 << HSPI_WIRE_POS)   //MOSI and MISO separated
#define HSPI_WIRE(param)  (HSPI_WIRE_##param >> HSPI_WIRE_POS)
/*
*/
#define HSPI_CPOL_HIGH    (0 << HSPI_CPOL_POS)   
#define HSPI_CPOL_LOW     (1 << HSPI_CPOL_POS)  
#define HSPI_CPOL(param)  (HSPI_CPOL_##param >> HSPI_CPOL_POS)
/*
*/
#define HSPI_CPHA_1EDGE   (0 << HSPI_CPHA_POS)   
#define HSPI_CPHA_2EDGE   (1 << HSPI_CPHA_POS) 
#define HSPI_CPHA(param)  (HSPI_CPHA_##param >> HSPI_CPHA_POS)
/*
*/
#define HSPI_NSS_SOFT    (0 << HSPI_NSS_POS)   
#define HSPI_NSS_HARD    (1 << HSPI_NSS_POS)
#define HSPI_NSS(param)  (HSPI_NSS_##param >> HSPI_NSS_POS)
/*
*/
#define HSPI_FB_MSB      (0 << HSPI_FB_POS)   
#define HSPI_FB_LSB      (1 << HSPI_FB_POS)
#define HSPI_FB(param)   (HSPI_FB_##param >> HSPI_FB_POS)
/*
*/
#define HSPI_BRP_2       (0 << HSPI_BRP_POS)
#define HSPI_BRP_4       (1 << HSPI_BRP_POS)
#define HSPI_BRP_8       (2 << HSPI_BRP_POS)
#define HSPI_BRP_16      (3 << HSPI_BRP_POS)
#define HSPI_BRP_32      (4 << HSPI_BRP_POS)
#define HSPI_BRP_64      (5 << HSPI_BRP_POS)
#define HSPI_BRP_128     (6 << HSPI_BRP_POS)
#define HSPI_BRP_256     (7 << HSPI_BRP_POS)
#define HSPI_BRP(param)  (HSPI_BRP_##param >> HSPI_BRP_POS)
/*
*/
#define HSPI_CFG_EXTRACT(cfg, name)  ((cfg >> HSPI_##name##_POS) & HSPI_##name##_MASK)
/*
*/
#define HSPI_DEVICE_MAX 5
/*
*/
class HAL_SPI
{
public:
  HAL_SPI():
    port(0),
    cfg(0),
    data_bits(8),
    device_number(0),
    busy(false),
    mosi_pin(nullptr),
    miso_pin(nullptr),
    sck_pin(nullptr),
    device{0}
  {}
  
  uint32_t port;
  uint32_t cfg;
  uint8_t data_bits;
  uint8_t device_number;
  bool busy;
  HAL_GPIO *mosi_pin;
  HAL_GPIO *miso_pin;
  HAL_GPIO *sck_pin;
  struct {
    const char *name;
    HAL_GPIO *cs_pin;
  }device[HSPI_DEVICE_MAX];
  
  bool init(uint32_t cfg0);
  bool config(uint32_t cfg0);
  int transfer(uint8_t *tx_buffer, uint8_t *rx_buffer, uint32_t num);
  int transfer(uint16_t *tx_buffer, uint16_t *rx_buffer, uint32_t num);
  int read(uint8_t *buffer, uint32_t num);
  int read(uint16_t *buffer, uint32_t num);
  int write(uint8_t *buffer, uint32_t num);
  int write(uint16_t *buffer, uint32_t num);
  void attach_pin(HAL_GPIO *mosi_pin0, HAL_GPIO *miso_pin0, HAL_GPIO *sck_pin0) {
    mosi_pin = mosi_pin0;
    miso_pin = miso_pin0;
    sck_pin = sck_pin0;
  }
  void detach_pin() {
    attach_pin(nullptr, nullptr, nullptr);
  }     
  
  int add_device(const char *name0, HAL_GPIO *cs_pin0);
  int get_device(const char *name0);
  bool device_select(uint8_t index, int ms);
  void device_free(uint8_t index);
};





